﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace Sci7z
{
    class _7zTool
    {
        /// <summary>
        /// 根据给的文件参数，自动进行压缩或解压缩操作
        /// </summary>
        public static void Process(String[] files)
        {
            if (files.Length > 0)
            {
                string Name = files[0].ToLower();
                if (files.Length == 1 && (Name.EndsWith(".zip") || Name.EndsWith(".rar") || Name.EndsWith(".7z")))
                    unzip(files[0]);
                else zip(files);
            }
        }


        /// <summary>
        /// 对文件目录DirPath中的文件进行压缩，压缩为zipPath
        /// </summary>
        public static bool zipDir(string DirPath, string zipPath = null, bool dependsDelet = false)
        {
            if (zipPath == null || zipPath.Equals("")) zipPath = getParent(DirPath) + ".7z";

            String[] subFiles = getSubFiles(new string[] { DirPath });	// 获取DirPath目录下的文件列表
            bool result = zip(subFiles, zipPath, dependsDelet);			// 对目录中的文件进行压缩操作
            return result;
        }

        /// <summary>
        /// 对所有files文件进行压缩，压缩为zipPath
        /// </summary>
        public static bool zip(string[] files, string zipPath = null, bool dependsDelet = false)
        {
            Depends.Export();

            if (files == null || files.Length == 0) return false;
            if (zipPath == null || zipPath.Equals("")) zipPath = getPathNoExt(files[0]) + ".7z";	// 默认以第一个文件命名压缩文件

            string tool7z = curDir() + "7z.exe";
            string cmd = AddQutation(tool7z) + " a -t7z " + AddQutation(zipPath);
            foreach (string file in files) cmd += " " + AddQutation(file);

            string result = Run(cmd);

            if (dependsDelet) AutoDelet.deletFiles(new string[] { "7z.exe", "7z.dll" });

            bool success = result.Contains("Everything is Ok");
            return success;
        }

        /// <summary>
        /// 解压缩文件zipPath至目录DirPath
        /// </summary>
        public static bool unzip(String zipPath, String DirPath = null, bool dependsDelet = false)
        {
            Depends.Export();

            if (DirPath == null) DirPath = Directory.GetParent(zipPath) + "\\" + Path.GetFileNameWithoutExtension(zipPath);

            string tool7z = curDir() + "7z.exe";
            string cmd = AddQutation(tool7z) + " x " + AddQutation(zipPath) + " " + AddQutation("-o" + DirPath);
            string result = Run(cmd);

            if (dependsDelet) AutoDelet.deletFiles(new string[] { "7z.exe", "7z.dll" });

            bool success = result.Contains("Compressed") && result.Contains("Everything is Ok");
            return success;
        }


        #region 压缩解压相关处理逻辑

        /// <summary>
        /// 获取当前运行路径
        /// </summary>
        private static string curDir()
        {
            return AppDomain.CurrentDomain.BaseDirectory;
        }

        /// <summary>
        /// 获取去除拓展名的文件路径
        /// </summary>
        private static String getPathNoExt(String path)
        {
            return Directory.GetParent(path).FullName + "\\" + Path.GetFileNameWithoutExtension(path);
        }

        /// <summary>
        /// 获取父目录的路径信息
        /// </summary>
        private static String getParent(String path)
        {
            return System.IO.Directory.GetParent(path).FullName + "\\";
        }

        /// <summary>
        /// 添加引号
        /// </summary>
        private static string AddQutation(String filePath)
        {
            return "\"" + filePath + "\"";
        }

        //-----------------------------------------------------------------------------------------

        /// <summary>
        /// 获取paths路径下所有文件信息
        /// </summary>
        private static String[] getSubFiles(String[] Paths)
        {
            List<String> list = new List<String>();	        // paths路径下所有文件信息

            foreach (String path in Paths)
            {
                List<String> subFiles = getSubFiles(path);	// 获取路径path下所有文件列表信息
                list = ListAdd(list, subFiles);
            }

            String[] A = List2Array(list);					// 转化为数组形式

            return A;
        }

        /// <summary>
        /// 合并list1和list2到新的list
        /// </summary>
        private static List<String> ListAdd(List<String> list1, List<String> list2)
        {
            List<String> list = new List<String>();

            foreach (String path in list1) if (!list.Contains(path)) list.Add(path);
            foreach (String path in list2) if (!list.Contains(path)) list.Add(path);

            return list;
        }

        /// <summary>
        /// 获取file目录下所有文件列表
        /// </summary>
        private static List<String> getSubFiles(String file)
        {
            List<String> list = new List<String>();

            if (File.Exists(file))
            {
                if (!list.Contains(file)) list.Add(file);
            }

            if (Directory.Exists(file))
            {
                long fCount = 0;
                foreach (String iteam in Directory.GetFiles(file))
                {
                    fCount++;
                    List<String> L = getSubFiles(iteam);	// 获取子目录下所有文件列表
                    foreach (String path in L)
                    {
                        if (!list.Contains(path)) list.Add(path);
                    }
                }

                long dCount = 0;
                foreach (String iteam in Directory.GetDirectories(file))
                {
                    dCount++;
                    List<String> L = getSubFiles(iteam);	// 获取子目录下所有文件列表
                    foreach (String path in L)
                    {
                        if (!list.Contains(path)) list.Add(path);
                    }
                }

                if (fCount == 0 && dCount == 0 && !list.Contains(file)) list.Add(file);
            }

            return list;
        }

        /// <summary>
        /// 转化list为数组
        /// </summary>
        private static String[] List2Array(List<String> list)
        {
            int size = (list == null ? 0 : list.Count);
            String[] A = new String[size];

            int i = 0;
            foreach (String S in list)
            {
                A[i++] = S;
            }

            return A;
        }


        static Process P = null;

        /// <summary>
        /// 执行CMD命令
        /// </summary>
        private static string Run(string cmd)
        {
            //Process P = newProcess("cmd.exe");
            if (P == null) P = newProcess("cmd.exe");
            else P.Start();

            P.StandardInput.WriteLine(cmd);
            P.StandardInput.WriteLine("exit");
            string outStr = P.StandardOutput.ReadToEnd();

            //P.Close();
            return outStr;
        }

        /// <summary>
        /// 以后台进程的形式执行应用程序（d:\*.exe）
        /// </summary>
        private static Process newProcess(String exe)
        {
            Process P = new Process();
            P.StartInfo.CreateNoWindow = true;
            P.StartInfo.FileName = exe;
            P.StartInfo.UseShellExecute = false;
            P.StartInfo.RedirectStandardError = true;
            P.StartInfo.RedirectStandardInput = true;
            P.StartInfo.RedirectStandardOutput = true;
            //P.StartInfo.WorkingDirectory = @"C:\windows\system32";
            P.Start();
            return P;
        }

        #endregion

    }
}
